#include "gamecontroller.h"

#include "view.h"
#include "model.h"
#include "util/loghandler.h"
#include "movableobject.h"
#include "gameconsole.h"

//using namespace Ogre;
using namespace spacedefender;



GameController::GameController(View* view, Model* model)
{
	_view = view;
	_model = model;
	_keepRunning = true;
	_consoleKeyPressed = false;
	_consoleMode = false;
}

GameController::~GameController()
{
	_inputManager->destroyInputObject(_keyboard);
	_inputManager->destroyInputObject(_mouse);
	OIS::InputManager::destroyInputSystem(_inputManager);
	
	if(_view)
	{
		_view = 0;
	}
	
	if(_model)
	{
		_model = 0;
	}
}


/*
	Maybe should let the view be the framehandler
*/

bool GameController::frameStarted(const Ogre::FrameEvent& evt)
{
	Ogre::WindowEventUtilities::messagePump();

	// call frameStarted of current state
	if(_mouse)
	{
		_mouse->capture();
	}
	
    if(_keyboard)
    {
        _keyboard->capture();
	}
	
	if(_keyboard->isKeyDown(OIS::KC_ESCAPE))
	{
		_keepRunning = false;
	}
	
	if(_keyboard->isKeyDown(OIS::KC_F1) && !_consoleKeyPressed)
	{
		if(_view->GetConsole()->IsVisible())
		{
			_keyboard->setBuffered(false);
			_mouse->setBuffered(false);
			_consoleMode = false;
			_view->GetConsole()->SetVisible(false);
		}
		else
		{
			_keyboard->setBuffered(true);
			_mouse->setBuffered(true);
			_consoleMode = true;
			_view->GetConsole()->SetVisible(true);
		}
		
		_consoleKeyPressed = true;
	}
	else if(!_keyboard->isKeyDown(OIS::KC_F1))
	{
		_consoleKeyPressed = false;
	}


	if(!_consoleMode)
		MoveShip( evt.timeSinceLastFrame);
	
	return _keepRunning;
}

bool GameController::frameEnded(const Ogre::FrameEvent& evt)
{
   return true;
}


// MouseListener
bool GameController::mouseMoved(const OIS::MouseEvent &evt)
{
	//CEGUI::System::getSingleton().injectMouseMove(arg.state.X.rel, arg.state.Y.rel);
    //return mStates.back()->mouseMoved(evt);
    return true;
}
bool GameController::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
{
	//CEGUI::System::getSingleton().injectMouseButtonDown(convertButton(id));
    //return mStates.back()->mousePressed(evt, id);
    return true;
}

bool GameController::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
{
	//CEGUI::System::getSingleton().injectMouseButtonUp(convertButton(id));
	//return mStates.back()->mouseReleased(evt, id);
	return true;
}

// KeyListener
bool GameController::keyPressed(const OIS::KeyEvent &evt)
{	
	if (evt.key == OIS::KC_ESCAPE)
	{
		_keepRunning = false;
	}
	
	if (_consoleMode && evt.key == OIS::KC_F1)
	{
		if(_view->GetConsole()->IsVisible())
		{
			_keyboard->setBuffered(false);
			_mouse->setBuffered(false);
			_consoleMode = false;
			_view->GetConsole()->SetVisible(false);
		}
		else
		{
			_keyboard->setBuffered(true);
			_mouse->setBuffered(true);
			_consoleMode = true;
			_view->GetConsole()->SetVisible(true);
		}
	}
	
	if(_consoleMode)
		_view->GetConsole()->onKeyPressed(evt);
	
    return true;
}
bool GameController::keyReleased(const OIS::KeyEvent &evt)
{
	//CEGUI::System::getSingleton().injectKeyUp(arg.key);
	
    return true; //mStates.back()->keyReleased(evt);
}


bool GameController::SetupInputSystem()
{
	size_t windowHnd = 0;
    std::ostringstream windowHndStr;
    OIS::ParamList pl;
    
	_view->GetWindow()->getCustomAttribute("WINDOW", &windowHnd);
    windowHndStr << windowHnd;
    pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
    _inputManager = OIS::InputManager::createInputSystem(pl);
    
    try
    {
        _keyboard = static_cast<OIS::Keyboard*>(_inputManager->createInputObject(OIS::OISKeyboard, false));
        _keyboard->setEventCallback(this);
        _mouse = static_cast<OIS::Mouse*>(_inputManager->createInputObject(OIS::OISMouse, false));
        _mouse->setEventCallback(this);
        
		_view->AddFrameListener(this);
    }
    catch (const OIS::Exception &e)
    {
        Loghandler::GetInstance()->Log("Exception in GameController::SetupInputSystem. " + std::string(e.eText));
        return false;
    }
	return true;
}

void GameController::MoveShip(Ogre::Real timeSinceLastFrame)
{
	MovableObject* playerShip = _model->GetPlayerShip();

	const float movementSpeed = 0.1f;
	float moveScale = movementSpeed * timeSinceLastFrame;
	
	Ogre::Degree rotationSpeed(5.6);
	Ogre::Degree rotationScale  = rotationSpeed * timeSinceLastFrame;
		
	Ogre::Vector3 translateVector = Ogre::Vector3::ZERO;
	
	// Move camera upwards along to world's Y-axis.
	//if(_inputManager->isKeyDown(Ogre::KC_PGUP))
	//	this->cameraNode->setPosition(this->cameraNode->getPosition() + Ogre::Vector3(0, 5, 0));

	// Move camera downwards along to world's Y-axis.
	//if(_inputManager->isKeyDown(Ogre::KC_PGDOWN))
	//	this->cameraNode->setPosition(this->cameraNode->getPosition() - Ogre::Vector3(0, 5, 0));

	// Move camera forward.
	//if(_inputManager->isKeyDown(Ogre::KC_UP))
	//	this->translateVector.z = -(this->moveScale);

	// Move camera backward.
	//if(_inputManager->isKeyDown(Ogre::KC_DOWN))
	//	this->translateVector.z = this->moveScale;

	// Move camera left.
	//if(_inputManager->isKeyDown(Ogre::KC_LEFT))
	//	this->translateVector.x = -(this->moveScale);

	// Move camera right.
	//if(_inputManager->isKeyDown(Ogre::KC_RIGHT))
	//	this->translateVector.x = this->moveScale;

	// Rotate camera left.
	if(_keyboard->isKeyDown(OIS::KC_A))
	{
		playerShip->Yaw((float)timeSinceLastFrame, true);
		//_view->Yaw(rotationScale);
	}
	
	// Rotate camera right.
	if(_keyboard->isKeyDown(OIS::KC_D))
	{
		playerShip->Yaw((float)timeSinceLastFrame, false);
		//_view->Yaw(-rotationScale);
	}
	
	// Strip all yaw rotation on the camera.
	//if(_inputManager->isKeyDown(Ogre::KC_A))
	//	this->cameraYawNode->setOrientation(Ogre::Quaternion::IDENTITY);

	// Rotate camera upwards.
	if(_keyboard->isKeyDown(OIS::KC_S))
	{
		playerShip->Pitch((float)timeSinceLastFrame, true);
		//_view->Pitch(rotationScale);
	}
	
	// Rotate camera downwards.
	if(_keyboard->isKeyDown(OIS::KC_W))
	{
		playerShip->Pitch((float)timeSinceLastFrame, false);
		//_view->Pitch(-rotationScale);
	}
	
	// Strip all pitch rotation on the camera.
	//if(_inputManager->isKeyDown(Ogre::KC_E))
	//	this->cameraPitchNode->setOrientation(Ogre::Quaternion::IDENTITY);

	// Tilt camera on the left.
	if(_keyboard->isKeyDown(OIS::KC_Q))
	{
		playerShip->Roll((float)timeSinceLastFrame, true);
		//_view->Roll(rotationScale);
	}
	
	// Tilt camera on the right.
	if(_keyboard->isKeyDown(OIS::KC_E))
	{
		playerShip->Roll((float)timeSinceLastFrame, false);
		//_view->Roll(-rotationScale);
	}

	if(_keyboard->isKeyDown(OIS::KC_UP))
	{
		playerShip->Move(timeSinceLastFrame);
	}

	if(_keyboard->isKeyDown(OIS::KC_DOWN))
	{
		playerShip->Move(-timeSinceLastFrame);
	}


	// Strip all tilt applied to the camera.
	/*if(_inputManager->isKeyDown(Ogre::KC_P))
		this->cameraRollNode->setOrientation(Ogre::Quaternion::IDENTITY);

	// Strip all rotation to the camera.
	if(_inputManager->isKeyDown(Ogre::KC_O))
	{
		this->cameraYawNode->setOrientation(Ogre::Quaternion::IDENTITY);
		this->cameraPitchNode->setOrientation(Ogre::Quaternion::IDENTITY);
		this->cameraRollNode->setOrientation(Ogre::Quaternion::IDENTITY);
	}*/
	
	
}
